package cn.chinaunicom.sdsi.frm.workflow.deployment.service.impl;

import java.util.List;

import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.chinaunicom.sdsi.frm.workflow.deployment.controller.bean.ProcessDefinitionVO;
import cn.chinaunicom.sdsi.frm.workflow.deployment.dao.ProcessDefinitionDao;
import cn.chinaunicom.sdsi.frm.workflow.deployment.service.ProcessDefinitionService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * 工作流发布模块流程定义相关组件
 * 
 * @author liyh
 * 
 */
@Service("processDefinitionService")
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {

	private static final Log log = LogFactory
			.getLog(ProcessDefinitionServiceImpl.class);

	/**
	 * 流程定义数据库访问层组件
	 */
	private ProcessDefinitionDao processDefinitionDao;

	/**
	 * 分页查询流程定义
	 * 
	 * 范围仅限已定义的最新流程 发布多次的流程使用最新的流程定义，使用流程定义中key区分
	 */
	@Override
	public JSONObject list4Page(ProcessDefinitionVO vo, int firstResult,
			int maxResults) {
		/*
		 * 获取分页的结果集
		 */
		List<ProcessDefinition> pdList = this.getProcessDefinitionDao()
				.list4Page(vo, firstResult, maxResults);
		/*
		 * 获取查询结果的总条数及符合记录条数
		 */
		long filteredCount = this.getProcessDefinitionDao().listFilteredCount(
				vo);
		long totalCount = this.getProcessDefinitionDao().listTotalCount(vo);

		JSONArray array = new JSONArray();
		JSONObject obj = null;

		for (ProcessDefinition pd : pdList) {
			obj = new JSONObject();
			// 流程定义表主键
			obj.element("id", pd.getId());
			// 流程定义的名称,对应XML文件中process中的name
			obj.element("name", pd.getName());
			// 流程定义的key,对应XML文件中process中的id
			obj.element("key", pd.getKey());
			// 对应部署数据表ID
			obj.element("deploymentId", pd.getDeploymentId());
			// 流程类型，对应XML文件中targetNamespace
			obj.element("category", pd.getCategory());
			// 流程定义的版本
			obj.element("version", pd.getVersion());
			// 流程描述
			obj.element("description", pd.getDescription());
			// 流程对应流程图资源名称
			obj.element("diagramResourceName", pd.getDiagramResourceName());
			// 流程是否激活
			obj.element("suspended", pd.isSuspended());
			// 通常为对应流程文件的相对路径
			obj.element("resourceName", pd.getResourceName());
			obj.element("tenantId", pd.getTenantId());

			array.add(obj);
		}
		log.debug("search ProcessDefinition change to json done");

		obj = new JSONObject();
		obj.element("data", array);
		obj.element("recordsFiltered", filteredCount);
		obj.element("recordsTotal", totalCount);
		obj.element("draw", 0);

		log.debug("search ProcessDefinition data for jquery datatables done");
		return obj;
	}

	/**
	 * 依据传入的流程key判断是否为新增流程
	 * 
	 * @param key
	 * @return
	 */
	@Override
	public JSONObject isNewProcess(ProcessDefinitionVO vo) {

		String key = vo.getKey();
		long num = this.getProcessDefinitionDao().findNumByKey(key);
		log.debug("search ProcessDefinition num with key done");

		JSONObject obj = new JSONObject();
		if (num > 0) {
			obj.element("newProcess", false);
		} else {
			obj.element("newProcess", true);
		}

		return obj;
	}

	/**
	 * 据传入的对象获取key进行发布
	 * 
	 * @param vo
	 * @return
	 */
	@Override
	public JSONObject addProcessByResource(ProcessDefinitionVO vo) {

		String key = vo.getKey();
		StringBuilder resourcePath = new StringBuilder("bpmn/").append(key)
				.append(".bpmn");

		// 记录是否发布成功
		boolean success = false;

		String deploymentId = this.getProcessDefinitionDao()
				.deploymentProcessByResource(resourcePath.toString());

		if (!StringUtils.isBlank(deploymentId)
				&& Long.parseLong(deploymentId) > 0) {
			success = true;
		}

		log.debug("deployment process with ProcessDefinition to get deploymentId:"
				+ deploymentId);

		JSONObject obj = new JSONObject();
		obj.element("success", success);

		return obj;
	}

	public ProcessDefinitionDao getProcessDefinitionDao() {
		return processDefinitionDao;
	}

	@Autowired
	public void setProcessDefinitionDao(
			ProcessDefinitionDao processDefinitionDao) {
		this.processDefinitionDao = processDefinitionDao;
	}
}
